home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Celestin Apprentice 5
/
Apprentice-Release5.iso
/
Source Code
/
Libraries
/
CW GUSI 1.6.4
/
doc
/
pod
/
GUSI_Misc.pod
< prev
next >
Wrap
Text File
|
1995-04-20
|
9KB
|
204 lines
=head1 Miscellaneous
=head2 BSD memory routines
These are implemented as macros if you
#include <compat.h>
C<void bzero(void * from, int len)> zeroes
C<len> bytes, starting at
C<from>.
C<void bfill(void * from, int len, int x)> fills
C<len> bytes, starting at
C<from> with
C<x>.
C<void bcopy(void * from, void * to, int len)> copies
C<len> bytes from
C<from> to
C<to>.
C<int bcmp(void * s1, void * s2, int len)> compares
C<len> bytes at
C<s1> against
C<len> bytes at
C<s2>, returning zero if the two areas are equal, nonzero otherwise.
=head2 Hooks
You can override some of GUSI's behaviour by providing hooks to GUSI. Note that these
often get called from deep within GUSI, so be sure you understand what is required
of a hook before overriding it.
GUSI hooks can be accessed with the following routines:
typedef void (*GUSIHook)(void);
void GUSISetHook(GUSIHookCode code, GUSIHook hook);
GUSIHook GUSIGetHook(GUSIHookCode code);
Currently, two hooks are defined. The C<GUSI_SpinHook> is defined in the next section.
The C<GUSI_ExecHook> is used by GUSI to decide whether a file or folder is to be
considered "executable" or not. The default hook considers all folders and all
applications (i.e., files of type C<'APPL'> and C<'appe'> to be executable. To provide
your own hook, call
GUSISetHook(GUSI_ExecHook, (GUSIHook) my_exec_hook);
where C<my_exec_hook> is defined as
Boolean my_exec_hook(const GUSIFileRef & ref);
The old value is available as:
Boolean (*)(const GUSIFileRef & ref)GUSIgetHook(GUSI_ExecHook);
=head2 Blocking calls
Since the Macintosh doesn't have preemptive task switching, it
is important that other applications get a chance to run during blocking calls. This
section discusses the mechanism C<GUSI> uses for that purpose.
While a routine is waiting for a blocking call to terminate, it repeatedly calls a
spin routine with the following parameters:
typedef enum spin_msg
{
SP_MISC, /* some weird thing, usually just return immediately if you get this */
SP_SELECT, /* in a select call, passes ticks the program is prepared to wait */
SP_NAME, /* getting a host by name */
SP_ADDR, /* getting a host by address */
SP_STREAM_READ, /* Stream read call */
SP_STREAM_WRITE, /* Stream write call */
SP_DGRAM_READ, /* Datagram read call */
SP_DGRAM_WRITE, /* Datagram write call */
SP_SLEEP, /* sleeping, passes ticks left to sleep */
SP_AUTO_SPIN /* Automatically spinning, passes spin count */
} spin_msg;
typedef int (*GUSISpinFn)(spin_msg msg, long param);
If the spin routine returns a nonzero value, the call is interrupted and
C<EINTR> returned. You can modify the spin routine with the following calls:
GUSISetHook(GUSI_SpinHook, (GUSIHook) my_spin_hook);
(GUSISpinFn)GUSIGetHook(GUSI_SpinHook);
(For backward compatibility, GUSI also defines the equivalents:)
int GUSISetSpin(GUSISpinFn routine);
GUSISpinFn GUSIGetSpin(void);
Often, however, the default spin routine will do what you want: It spins a
cursor and occasionally calls C<GetNextEvent()> or C<WaitNextEvent()>. By default,
only mouse down and suspend/resume events are handled, but you can change that
by passing your own C<GUSIEvtTable> to C<GUSISetEvents()>.
int GUSISetEvents(GUSIEvtTable table);
GUSIEvtHandler * GUSIGetEvents(void);
A C<GUSIEvtTable> is a table of C<GUSIEvtHandlers>, indexed by event code. Presence
of a non-nil entry in the table will cause that event class to be allowed for
C<GetNextEvent()> or C<WaitNextEvent()>. C<GUSI> for C<MPW C> and C<PPCC> includes
one event table to be used with the C<SIOW> library.
typedef void (*GUSIEvtHandler)(EventRecord * ev);
typedef GUSIEvtHandler GUSIEvtTable[24];
extern GUSIEvtHandler GUSISIOWEvents[];
C<GUSI> also supports three POSIX/BSD routines: C<alarm(unsigned sec)> will after
C<sec> seconds cancel the current call, raise C<SIGALRM>, and return C<EINTR>.
Note that the default handler for C<SIGALRM> terminates the program, so be sure
to install your own handler. C<alarm(0)> cancels an alarm and returns the remaining
seconds. As opposed to POSIX systems, the C<GUSI> version of C<alarm()> does not use
real clock interrupts and merely interrupts during a blocking call.
C<sleep(unsigned sec)> sleeps for C<sec> seconds, and C<usleep(unsigned usec)> does
the same for C<usec> micorseconds (rounded to 60ths of a tick).
=head2 Resources
A few C<GUSI> routines (currently primarily choose()) need resources
to work correctly. These are added if you Rez your program with C<GUSI.r>. On
startup, C<GUSI> also looks for a I<preference> resource with type
C<'GUZI'> (the C<'Z'> actually must be a capital Sigma) and ID C<GUSIRsrcID>,
which is currently defined as follows:
#ifndef GUSI_PREF_VERSION
#define GUSI_PREF_VERSION '0102'
#endif
type 'GUZI' {
literal longint text = 'TEXT'; /* Type for creat'ed files */
literal longint mpw = 'MPS '; /* Creator for creat'ed files */
byte noAutoSpin, autoSpin; /* Automatically spin cursor ? */
#if GUSI_PREF_VERSION >= '0110'
boolean useChdir, dontUseChdir; /* Use chdir() ? */
boolean approxStat, accurateStat; /* statbuf.st_nlink = # of subdirectories ? */
boolean noTCPDaemon, isTCPDaemon; /* Inetd client ? */
boolean noUDPDaemon, isUDPDaemon;
#if GUSI_PREF_VERSION >= '0150'
boolean noConsole, hasConsole; /* Are we providing our own dev:console ? */
fill bit[3];
#else
fill bit[4];
#endif
literal longint = GUSI_PREF_VERSION;
#if GUSI_PREF_VERSION >= '0120'
integer = @t$$@>Countof(SuffixArray);
wide array SuffixArray {
literal longint; /* Suffix of file */
literal longint; /* Type for file */
literal longint; /* Creator for file */
};
#endif
#endif
};
To keep backwards compatible, the preference version is included, and you are free to
use whatever version of the preferences you want by defining C<GUSI_PREF_VERSION>.
The first two fields define the file type and creator, respectively, to be used
for files created by C<GUSI>. The type and creator of existing files will never
be changed unless explicitely requested with fsetfileinfo(). The default is to
create text files (type `TEXT') owned by the C<MPW Shell> (creator `MPS '). If you
request a preference version of 1.2.0 and higher, you are also allowed to specify
a list of suffixes that are given different types. An example of such a list would be:
{ 'SYM ', 'MPSY', 'sade' }
The C<autoSpin> value, if nonzero, makes C<GUSI> call the spin routine for every
call to C<read()>, C<write()>, C<send()>, or C<recv()>. This is useful for making
an I/O bound program MultiFinder friendly without having to insert explicit calls
to C<SpinCursor()>. If you don't specify a preference resource, C<autoSpin> is assumed
to be C<1>. You may specify arbitrary values greater than one to make your program
even friendlier; note, however, that this will hurt performance.
The C<useChdir> flag tells C<GUSI> whether you change directories with the
toolbox calls C<PBSetVol()> or C<PBHSetVol()> or with the C<GUSI> call C<chdir()>.
The current directory will start with the directory your application resides in
or the current C<MPW> directory, if you're running an C<MPW> tool.
If C<useChdir> is specified, the current directory will only change with C<chdir()>
calls. If C<dontUseChdir> is specified, the current directory will change with
toolbox calls, until you call C<chdir()> the first time. This behaviour is more
consistent with the standard C<MPW> library, but has IMHO no other redeeming
value. If you don't specify a preference resource, C<useChdir> is assumed.
If C<approxStat> is specified, C<stat()> and C<lstat()> for directories return in
C<st_nlink> the number of I<items> in the directory C<+ 2>. If C<accurateStat> is
specified, they return the number of I<subdirectories> in the directory. The
latter has probably the best chances of being compatible with some Unix software,
but the former is often a sufficient upper bound, is much faster, and most programs
don't care about this value anyway. If you don't specify a preference resource,
C<approxStat> is assumed.
The C<isTCPDaemon> and C<isUDPDaemon> flags turn C<GUSI> programs into clients
for David Petersons C<inetd>, as discussed below. If you don't specify a preference
resource, C<noTCPDaemon> and C<noUDPDaemon> are assumed.
The C<hasConsole> flag should be set if you are overriding the default "dev:console",
as discussed below.